{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#  Convolutional Neural Network\n",
    "\n",
    "### Convolutional Layers: [128,128,128] ; Dense Layers [128,128,128] \n",
    "### CNN regularized with max-norm regularization\n",
    "\n",
    "CNN is trained on raw data"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##  Get the data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Stored variables and their in-db values:\n",
      "X_test              -> defaultdict(<class 'list'>, {0: array([[[-0.000654\n",
      "X_train             -> array([[[-0.00107939, -0.00131855, -0.00122601, ..\n",
      "snrs                -> [-20, -18, -16, -14, -12, -10, -8, -6, -4, -2, 0, \n",
      "y_test              -> defaultdict(<class 'list'>, {0: array([5, 5, 5, ..\n",
      "y_train             -> array([4, 6, 7, ..., 2, 7, 4])\n"
     ]
    }
   ],
   "source": [
    "import warnings\n",
    "warnings.filterwarnings('ignore')\n",
    "\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "import tensorflow as tf\n",
    "from collections import defaultdict\n",
    "from time import time\n",
    "\n",
    "%store -r\n",
    "%store"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Training data:  (80000, 2, 128) and labels:  (80000,)\n",
      "\n",
      "Test data:\n",
      "Total 20 (4000, 2, 128) arrays for SNR values:\n",
      "[-20, -18, -16, -14, -12, -10, -8, -6, -4, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18]\n"
     ]
    }
   ],
   "source": [
    "print(\"Training data: \", X_train.shape, \"and labels: \", y_train.shape)\n",
    "print()\n",
    "print(\"Test data:\")\n",
    "print(\"Total\", len(X_test), X_test[18].shape, \"arrays for SNR values:\")\n",
    "print(sorted(X_test.keys()))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##  Standardize the features"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Training set (80000, 2, 128)\n",
      "Test set corresponding to one snr value (4000, 2, 128)\n"
     ]
    }
   ],
   "source": [
    "from sklearn.preprocessing import StandardScaler\n",
    "\n",
    "sc = StandardScaler()\n",
    "_X_train = np.reshape(X_train, [X_train.shape[0], X_train.shape[1]*X_train.shape[2]])\n",
    "_X_train = sc.fit_transform(_X_train)\n",
    "\n",
    "X_train = np.reshape(_X_train, X_train.shape)\n",
    "print(\"Training set\", X_train.shape)\n",
    "\n",
    "_X_test = defaultdict(list)\n",
    "for snr in snrs:\n",
    "    _X_test[snr] = np.reshape(X_test[snr], [X_test[snr].shape[0], X_test[snr].shape[1]*X_test[snr].shape[2]])\n",
    "    _X_test[snr] = sc.transform(_X_test[snr])\n",
    "    X_test[snr] = np.reshape(_X_test[snr], X_test[snr].shape)\n",
    "    \n",
    "print(\"Test set corresponding to one snr value\", X_test[18].shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##  Design and train the CNN"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 0 training accuracy : 0.2421875\n",
      "INFO:tensorflow:Restoring parameters from ./CNN_regtech_maxnorm\n",
      "Epoch 1 training accuracy : 0.353515625\n",
      "INFO:tensorflow:Restoring parameters from ./CNN_regtech_maxnorm\n",
      "Epoch 2 training accuracy : 0.5380859375\n",
      "INFO:tensorflow:Restoring parameters from ./CNN_regtech_maxnorm\n",
      "Epoch 3 training accuracy : 0.537109375\n",
      "INFO:tensorflow:Restoring parameters from ./CNN_regtech_maxnorm\n",
      "Epoch 4 training accuracy : 0.5869140625\n",
      "INFO:tensorflow:Restoring parameters from ./CNN_regtech_maxnorm\n",
      "Epoch 5 training accuracy : 0.57421875\n",
      "INFO:tensorflow:Restoring parameters from ./CNN_regtech_maxnorm\n",
      "Epoch 6 training accuracy : 0.5615234375\n",
      "INFO:tensorflow:Restoring parameters from ./CNN_regtech_maxnorm\n",
      "Epoch 7 training accuracy : 0.6337890625\n",
      "INFO:tensorflow:Restoring parameters from ./CNN_regtech_maxnorm\n",
      "Epoch 8 training accuracy : 0.6328125\n",
      "INFO:tensorflow:Restoring parameters from ./CNN_regtech_maxnorm\n",
      "Epoch 9 training accuracy : 0.6513671875\n",
      "INFO:tensorflow:Restoring parameters from ./CNN_regtech_maxnorm\n",
      "INFO:tensorflow:Restoring parameters from ./CNN_regtech_maxnorm\n",
      "Training took 38.892321 minutes\n"
     ]
    }
   ],
   "source": [
    "height = 2\n",
    "width = 128\n",
    "channels = 1\n",
    "n_features = height * width\n",
    "\n",
    "feature_map1 = 128\n",
    "ksize_conv1 = 2\n",
    "stride_conv1 = 1\n",
    "\n",
    "feature_map2 = 128\n",
    "ksize_conv2 = ksize_conv1\n",
    "stride_conv2 = stride_conv1\n",
    "\n",
    "feature_map3 = 128\n",
    "ksize_conv3 = ksize_conv1\n",
    "stride_conv3 = stride_conv1\n",
    "\n",
    "pool_layer_maps = 128\n",
    "\n",
    "n_fully_conn1 = 128\n",
    "n_fully_conn2 = 128\n",
    "n_fully_conn3 = 128\n",
    "\n",
    "n_classes = 8\n",
    "\n",
    "max_clip_value = 1.0\n",
    "  \n",
    "X = tf.placeholder(tf.float32, shape=[None, height, width])\n",
    "X_reshaped = tf.reshape(X, shape=[-1, height, width, channels])\n",
    "labels = tf.placeholder(tf.int32, shape=[None])\n",
    "\n",
    "xavier_init = tf.contrib.layers.xavier_initializer()\n",
    "relu_act = tf.nn.relu\n",
    "\n",
    "# ------------------ Convolutional and pooling layers ----------------------------\n",
    "\n",
    "def convolutional_layer(X, filter_, ksize, kernel_init, strides, padding):\n",
    "    convolutional_layer = tf.layers.conv2d(X, filters = filter_, kernel_initializer = kernel_init,\n",
    "                                           kernel_size = ksize, strides = strides,\n",
    "                                          padding = padding, activation = relu_act)\n",
    "    return convolutional_layer\n",
    "\n",
    "def pool_layer(convlayer, ksize, strides, padding, pool_maps):\n",
    "    pool = tf.nn.max_pool(convlayer, ksize, strides, padding)\n",
    "    dim1, dim2 = int(pool.get_shape()[1]), int(pool.get_shape()[2])\n",
    "    pool_flat = tf.reshape(pool, shape = [-1, pool_maps * dim1 * dim2])\n",
    "    return pool_flat\n",
    "\n",
    "conv_layer1 = convolutional_layer(X_reshaped, feature_map1, ksize_conv1, xavier_init, stride_conv1, padding = \"SAME\")\n",
    "\n",
    "conv_layer2 = convolutional_layer(conv_layer1, feature_map2, ksize_conv2, xavier_init, stride_conv2, padding = \"SAME\")\n",
    "\n",
    "conv_layer3 = convolutional_layer(conv_layer2, feature_map3, ksize_conv3, xavier_init, stride_conv3, padding = \"SAME\")\n",
    "\n",
    "pool_layer_flat = pool_layer(conv_layer3, [1,2,2,1], [1,2,2,1], \"VALID\", pool_layer_maps)\n",
    "\n",
    "# ----------------- Fully connected layers -------------------\n",
    "\n",
    "def dense_layer(input_layer, n_neurons, kernel_init, activation, name):\n",
    "    fully_conn = tf.layers.dense(inputs = input_layer, units = n_neurons, activation = activation,\n",
    "                                kernel_initializer = kernel_init, name = name)\n",
    "    return fully_conn\n",
    "        \n",
    "dense_layer1 = dense_layer(pool_layer_flat, n_fully_conn1, xavier_init, relu_act, \"dense1\")\n",
    "\n",
    "dl1_weights = tf.get_default_graph().get_tensor_by_name(\"dense1/kernel:0\")\n",
    "clipped1 = tf.clip_by_norm(dl1_weights, clip_norm = max_clip_value, axes=1)\n",
    "dl1_clipped = tf.assign(dl1_weights, clipped1)\n",
    "\n",
    "dense_layer2 = dense_layer(dense_layer1, n_fully_conn2, xavier_init, relu_act, \"dense2\")\n",
    "\n",
    "dl2_weights = tf.get_default_graph().get_tensor_by_name(\"dense2/kernel:0\")\n",
    "clipped2 = tf.clip_by_norm(dl2_weights, clip_norm = max_clip_value, axes=1)\n",
    "dl2_clipped = tf.assign(dl2_weights, clipped2)\n",
    "\n",
    "dense_layer3 = dense_layer(dense_layer2, n_fully_conn3, xavier_init, relu_act, \"dense3\")\n",
    "\n",
    "dl3_weights = tf.get_default_graph().get_tensor_by_name(\"dense3/kernel:0\")\n",
    "clipped3 = tf.clip_by_norm(dl3_weights, clip_norm = max_clip_value, axes=1)\n",
    "dl3_clipped = tf.assign(dl3_weights, clipped3)\n",
    "\n",
    "# ----------------- Output softmax layer ---------------------------\n",
    "\n",
    "logits = tf.layers.dense(dense_layer3, n_classes)\n",
    "softmax_activations = tf.nn.softmax(logits)\n",
    "\n",
    "# ----------------- Specify performance measure -------------------------------\n",
    "\n",
    "cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(logits = logits, labels = labels)\n",
    "loss = tf.reduce_mean(cross_entropy)\n",
    "optimizer = tf.train.AdamOptimizer()\n",
    "train_operation = optimizer.minimize(loss)\n",
    "\n",
    "correct_predictions = tf.nn.in_top_k(logits, labels, 1)\n",
    "accuracy = tf.reduce_mean(tf.cast(correct_predictions, tf.float32))\n",
    "\n",
    "# ---------------- Execution phase -------------------------------------------\n",
    "    \n",
    "n_epochs = 10\n",
    "batch_size = 1024\n",
    "n_train = X_train.shape[0]\n",
    "n_iter = n_train//batch_size\n",
    "\n",
    "acc_test = defaultdict(list)\n",
    "\n",
    "path = \"./CNN_regtech_maxnorm\"  \n",
    "saver = tf.train.Saver()\n",
    "\n",
    "start = time()\n",
    "\n",
    "with tf.Session() as sess:\n",
    "    tf.global_variables_initializer().run()\n",
    "    for epoch in range(n_epochs):\n",
    "        for iteration in range(n_iter):\n",
    "            rand_indices = np.random.choice(n_train,batch_size)    \n",
    "            X_batch, y_batch = X_train[rand_indices], y_train[rand_indices]\n",
    "            sess.run(train_operation, feed_dict={X: X_batch, labels: y_batch})\n",
    "            dl1_clipped.eval()\n",
    "            dl2_clipped.eval()\n",
    "            dl3_clipped.eval()\n",
    "        acc_train = accuracy.eval(feed_dict={X: X_batch, labels: y_batch})\n",
    "        print(\"Epoch {} training accuracy : {}\".format(epoch, acc_train))\n",
    "        save_path = saver.save(sess, path)\n",
    "        saver.restore(sess, path)\n",
    "    saver.restore(sess, path)\n",
    "    for snr in snrs:\n",
    "        acc_test[snr] = accuracy.eval(feed_dict={X: X_test[snr], labels: y_test[snr]})\n",
    "\n",
    "print(\"Training took %f minutes\"%(float(time() - start)/60.0))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##  Test the classifier"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CNN's test accuracy on -20dB SNR samples = 0.12325000017881393\n",
      "CNN's test accuracy on -18dB SNR samples = 0.1287499964237213\n",
      "CNN's test accuracy on -16dB SNR samples = 0.13099999725818634\n",
      "CNN's test accuracy on -14dB SNR samples = 0.1432500034570694\n",
      "CNN's test accuracy on -12dB SNR samples = 0.18324999511241913\n",
      "CNN's test accuracy on -10dB SNR samples = 0.22675000131130219\n",
      "CNN's test accuracy on -8dB SNR samples = 0.304749995470047\n",
      "CNN's test accuracy on -6dB SNR samples = 0.3889999985694885\n",
      "CNN's test accuracy on -4dB SNR samples = 0.5067499876022339\n",
      "CNN's test accuracy on -2dB SNR samples = 0.656499981880188\n",
      "CNN's test accuracy on 0dB SNR samples = 0.7549999952316284\n",
      "CNN's test accuracy on 2dB SNR samples = 0.7982500195503235\n",
      "CNN's test accuracy on 4dB SNR samples = 0.8057500123977661\n",
      "CNN's test accuracy on 6dB SNR samples = 0.8137500286102295\n",
      "CNN's test accuracy on 8dB SNR samples = 0.8165000081062317\n",
      "CNN's test accuracy on 10dB SNR samples = 0.8289999961853027\n",
      "CNN's test accuracy on 12dB SNR samples = 0.8227499723434448\n",
      "CNN's test accuracy on 14dB SNR samples = 0.8190000057220459\n",
      "CNN's test accuracy on 16dB SNR samples = 0.8162500262260437\n",
      "CNN's test accuracy on 18dB SNR samples = 0.8230000138282776\n"
     ]
    }
   ],
   "source": [
    "for snr in snrs:\n",
    "    print(\"CNN's test accuracy on {}dB SNR samples = {}\".format(snr,acc_test[snr]))  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##  Visualize classifier's performance on test set"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\nh9QzJiIiIpJhedUzZmYTzGyxmS0xsxkJnt/NzJ40sxfN7Ckz2yXbYxQRERHJlqwWY2ZWAtwMjAc+\nCEw0s/26HDYXuNvdDwYuB67O5hh7Eva5bOUVZpbylKe84skL87UVQ14y2b4zdhiw1N2XuXsEuB84\nocsxHwCeAnD3pxM8LyIiIhIaWe0ZM7OTgPHuPi22PQk4zN2nxx0zH3jO3X9kZicCvwKGuvu6LudS\nz5iIiIgUhGQ9Y2XZHkuCfV0rqu8AN5vZZOCvwAqgLdHJJk+eTE1NDQDV1dWMGTOGcePGAVtvP2pb\n29rWtra1rW1tZ3u743F9fT3b5O5Z+wLGAk/EbV8MzEhyfD/grR6e82xasGCB8pSXd1nKU57yiicv\nzNdWDHmxuiVhvVOy7XItrRYCe5nZ7mZWAZwCPBJ/gJntZGYdd9C+C9yZ5TGKiIiIZE3W1xkzswnA\njQRvHrjD3a82s9nAQnd/LNZXdhUQJZimPNuDZv+u5/Fsj11ERERkeyTrGdOiryIiIiIZlleLvhaq\n+IY85SkvX7KUpzzlFU9emK+tGPKSUTEmIiIikkOaphQRERHJME1TioiIiOQpFWMpCvtctvIKM0t5\nylNe8eSF+dqKIS8ZFWMiIiIiOaSeMREREZEMU8+YiIiISJ5SMZaisM9lK68ws5SnPOUVT16Yr60Y\n8pJRMSYiIiKSQ+oZExEREckw9YyJiIiI5CkVYykK+1y28gozS3nKU17x5IX52oohLxkVYyIiIiI5\npJ4xERERkQxTz5iIiIhInlIxlqKwz2UrrzCzlKc85eUmr66unqlnz+KIYyYy9exZ1NXVZzwzrK9l\nseQlo2JMRESkF+rq6pk4bQ5LWiexqd8XWNI6iYnT5mSlIJNwUs+YiIhIL0w9exZLWidRWl61ZV97\npImK1Xdx2exLOfygqiTf3Xt1dfVcOfd2VjdEGFpdzswLp1BbW5PWjGKSq9czWc9YWcbTRURECoC7\ns2Z9O2+/38bylRGWr2xjQFUJkz49qNNxqxsilA7qXHCVllfx+tstPPLXjQmLsReXNDNn/loG9ith\nUP8SBvYrYWC/UvbZrYLjPtov4VjMbMtduMqa6ZQOqmJtaxMTp83hvnkXqSDbDvn6emqaMkVhn8tW\nXmFmKU95ygvsaA/X0rdb+dwFy/nyzHf49o0ruf6+dfzqz438eeGmbscOrS6nPdIEwLoVzwLBnbHd\ndq7giIP7Jjz/mg3tvLu6jdeWtfKvV5p58l9NPLygkb+/0JTw+H+8tJlPn/s2n570o6BwKK9i3Ypn\nKS2vorJmOlfOvb3T8avWtfHs/zbz39eaWVzfQv27Ed5f28amzdFevQ6Qm344yOzflUX1LTzw5AZO\nP/fHKb2e2aY7YyIiknYdU0GLXnuD/X/1ZEanguLvdmzq9yJLWg9m4tQ5zL3qfEoqR7F8ZRtvvx/c\n6YpG4cZvj+h2jqHVpWxucQb2K2H08DJ2HVHOrsPL2H3n8m7HzrxwypY8CAqxlvqbYndXBiQc48cP\n6ss9l+7Mhk1RNmyKsn5jOxs2Rdl5aOJfwxs2RWmJOC0t7Z2mQyG4C7e6IdJp34tLW7jy7jXdzvOp\nD1cx6+tDu+1f+Opm5j+xgb4VRp9Ko29lCX0qjaF93uNHN9/c+bWcNoeb514AFaOoLDcq4r4GVAV3\n+HbE9vxdWVzfwvOLm2nYGLyW6zdGaWhsZ/zY/pz4ye4/g3+/2sxdj61n2Tut1I7e9uuZbeoZExGR\ntOo0FVRe1aVYqUn4Pe5Oa8RpbYP+fQ2z7q01//zf5qBAicSOjX09+Zs5LI107+F664V51H7kvE7n\nKCmBJ27clbLSzud3dzZsijKof2qFRab7jtyd5hZn6rcu4W37ardr26diPrfdcsWWfc8vbuahpzaw\nuSX4vs0tUZpbnSMPqeLsLw3udv7fPbORH/58bbf9LXU/omz0Gd3y+m+4m807ndXt+PFj+zHjazt1\n2//085uY95sGKsqMigqjosyorDDGHtCX/3f0wC3HJfq78u5L13PksVPwytF86sNV3aaJAX715w3c\n+lBDt/1f+ER/pp88pNv+/yxu5tmXN/Pr+VcTGXb6Nl/PTFDPmIiIZJS789LrLazb0M5VV9665Zcr\n0GkqKP4X3sRZK9i0ObgDFGnbeq4nbtyViu43pLj0tlWdjuswYF2E0sHd73b0rXQ+vH8fdh1Rxujh\n5VvueJUmaNAxs5QLMYDa2pqM/vI2M/r2Mb7/vakJC9uZ8y7qdPyh+/Xh0P36pHz+jx3Yl+vPHx4U\nb62x4q3FueUGiCa4E9fc3M6H9q3cWgi3QWtrlMEDE79m6zdFeW9Ne7f9o4Z1/sFeOff2bn9Xdj7o\nfJ76Q1BIv7M6wQ8c2L+mklOOG0h1/6AHb1D/Uqr7lzB8SOKy5kP79eFD+/XhM4d+M6XXM9uyXoyZ\n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\nRK5CYII=\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7fbcb55a4390>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.style.use('classic')\n",
    "%matplotlib inline\n",
    "\n",
    "acc_test = sorted(acc_test.items())\n",
    "new_acc = []\n",
    "for i in range(len(acc_test)):\n",
    "    new_acc.append(acc_test[i][1])\n",
    "acc_test_values = new_acc \n",
    "\n",
    "fig1 = plt.figure(figsize=(10, 6), dpi=100)\n",
    "x = snrs\n",
    "y = list(acc_test_values)\n",
    "plt.plot(x, y, marker=\"o\", linewidth=2.0, linestyle='dashed', color='royalblue')\n",
    "plt.axis([-20, 20, 0, 1])\n",
    "plt.xticks(np.arange(min(x), max(x)+1, 2.0))\n",
    "plt.yticks(np.arange(0, 1, 0.10))\n",
    "\n",
    "ttl = plt.title('SNR vs Accuracy', fontsize=16)\n",
    "ttl.set_weight('bold')\n",
    "plt.xlabel('SNR (dB)', fontsize=14)\n",
    "plt.ylabel('Test accuracy', fontsize=14)\n",
    "plt.grid()\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "INFO:tensorflow:Restoring parameters from ./CNN_regtech_maxnorm\n",
      "Confusion Matrix\n",
      "       8PSK  BPSK  CPFSK  GFSK  PAM4  QAM16  QAM64  QPSK\n",
      "8PSK   0.81  0.00   0.00  0.00  0.00   0.05   0.03  0.12\n",
      "BPSK   0.00  0.96   0.00  0.00  0.02   0.01   0.00  0.01\n",
      "CPFSK  0.02  0.00   0.96  0.00  0.00   0.00   0.00  0.01\n",
      "GFSK   0.01  0.00   0.02  0.96  0.00   0.00   0.00  0.00\n",
      "PAM4   0.00  0.01   0.00  0.00  0.99   0.00   0.00  0.00\n",
      "QAM16  0.09  0.00   0.00  0.00  0.00   0.56   0.32  0.03\n",
      "QAM64  0.02  0.00   0.00  0.00  0.00   0.47   0.50  0.01\n",
      "QPSK   0.11  0.00   0.00  0.00  0.00   0.01   0.01  0.87\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7fbc3c7a1f28>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Confusion Matrix\n",
    "\n",
    "with tf.Session() as sess:\n",
    "    saver.restore(sess, path)\n",
    "    Z = logits.eval(feed_dict = {X : X_test[18]})\n",
    "    predicted_18dB = np.argmax(Z, axis = 1)\n",
    "    \n",
    "from sklearn.metrics import confusion_matrix\n",
    "%matplotlib inline\n",
    "\n",
    "classes = ['8PSK', 'BPSK', 'CPFSK', 'GFSK', 'PAM4', 'QAM16', 'QAM64', 'QPSK']\n",
    "conf_matrix = confusion_matrix(predicted_18dB, y_test[18])  \n",
    "\n",
    "conf_matrix = conf_matrix.astype('float') / conf_matrix.sum(axis=1)[:, np.newaxis]\n",
    "conf_matrix = conf_matrix.round(decimals = 2)\n",
    "\n",
    "import pandas as pd\n",
    "\n",
    "df = pd.DataFrame(data = conf_matrix, columns = classes, index = classes) \n",
    "print(\"Confusion Matrix\")\n",
    "print(df)\n",
    "\n",
    "fig1 = plt.figure(figsize=(10, 6), dpi=100)\n",
    "plt.imshow(conf_matrix, interpolation = 'nearest', cmap = plt.cm.Purples)\n",
    "ticks = np.arange(len(classes))\n",
    "plt.title(\"Confusion Matrix\")\n",
    "plt.xticks(ticks, classes, rotation=45)\n",
    "plt.yticks(ticks, classes)\n",
    "\n",
    "plt.ylabel('True class')\n",
    "plt.xlabel('Predicted class')\n",
    "\n",
    "plt.tight_layout()\n",
    "plt.colorbar()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
